package com.example.mvvm.base;

import android.os.Bundle;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;

import com.example.mvvm.base.BaseViewModel;
import com.example.mvvm.base.IBaseView;
import com.example.mvvm.base.livedata.MessageLiveEvent;
import com.example.mvvm.base.livedata.StatusLiveEvent;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Time: 4/30/2021 15:54
 * Author: TAO
 * Description:
 */
public abstract class BaseFragment<VM extends BaseViewModel, VDB extends ViewDataBinding> extends Fragment implements IBaseView<VM> {
    private VDB binging;
    private VM viewModel;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        if (getLayoutId() != 0) {

            if (isBinding()) {
                binging = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
                return binging.getRoot();
            } else {
                return inflater.inflate(getLayoutId(), container, false);
            }
        } else {
            return super.onCreateView(inflater, container, savedInstanceState);
        }
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initViewModel();
        initData(savedInstanceState);
    }

    /**
     * 初始化 {@link #viewModel}
     */
    private void initViewModel() {
        viewModel = createViewModel();
        if (viewModel != null) {
            getLifecycle().addObserver(viewModel);
            binging.setVariable(variableId(), viewModel);
            registerLoadingEvent();
        }
    }

    private Class<VM> getVMClass() {
        Class cls = getClass();
        Class<VM> vmClass = null;
        while (vmClass == null && cls != null) {
            vmClass = getVMClass(cls);
            cls = cls.getSuperclass();
        }
        if (vmClass == null) {
            vmClass = (Class<VM>) BaseViewModel.class;
        }
        return vmClass;
    }

    private Class getVMClass(Class cls) {
        Type type = cls.getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            Type[] types = ((ParameterizedType) type).getActualTypeArguments();
            for (Type t : types) {
                if (t instanceof Class) {
                    Class vmClass = (Class) t;
                    if (BaseViewModel.class.isAssignableFrom(vmClass)) {
                        return vmClass;
                    }
                } else if (t instanceof ParameterizedType) {
                    Type rawType = ((ParameterizedType) t).getRawType();
                    if (rawType instanceof Class) {
                        Class vmClass = (Class) rawType;
                        if (BaseViewModel.class.isAssignableFrom(vmClass)) {
                            return vmClass;
                        }
                    }
                }
            }
        }

        return null;
    }

    @Override
    public VM createViewModel() {
        return obtainViewModel(getVMClass());
    }

    /**
     * 通过 {@link #createViewModelProvider(ViewModelStoreOwner)}获得 ViewModel
     *
     * @param modelClass Class
     * @return ViewModel
     */
    public <T extends ViewModel> T obtainViewModel(@NonNull Class<T> modelClass) {
        return createViewModelProvider(this).get(modelClass);
    }

    /**
     * 创建 {@link ViewModelProvider}
     *
     * @param owner ViewModelStoreOwner实例对象
     * @return 返回实例
     */
    private ViewModelProvider createViewModelProvider(@NonNull ViewModelStoreOwner owner) {
        return new ViewModelProvider(owner, ViewModelProvider.AndroidViewModelFactory.getInstance(getActivity().getApplication()));
    }


    @Override
    public boolean isBinding() {
        return true;
    }


    @Override
    public void onDestroy() {
        if (viewModel != null) {
            getLifecycle().removeObserver(viewModel);
            viewModel = null;
        }

        if (binging != null) {
            binging.unbind();
            binging = null;
        }
        super.onDestroy();
    }


    public VDB getBinging() {
        return binging;
    }

    public VM getViewModel() {
        return viewModel;
    }

    /**
     * 注册状态加载事件
     */
    protected void registerLoadingEvent() {
        getViewModel().getLoadingEvent().observe(this, isLoading -> {
            if (isLoading) {
                showLoading();
            } else {
                hideLoading();
            }
        });
    }

    @Override
    public void showLoading() {

    }

    @Override
    public void hideLoading() {

    }

    /**
     * 注册消息事件
     */
    protected void registerMessageEvent(@NonNull MessageLiveEvent.MessageObserver observer) {
        getViewModel().getMessageEvent().observe(this, observer);
    }

    /**
     * 注册单个消息事件，消息对象:{@link Message}
     *
     * @param observer
     */
    protected void registerSingleLiveEvent(@NonNull Observer<Message> observer) {
        getViewModel().getSingleLiveEvent().observe(this, observer);
    }

    /**
     * 注册状态事件
     *
     * @param observer
     */
    protected void registerStatusEvent(@NonNull StatusLiveEvent.StatusObserver observer) {
        getViewModel().getStatusEvent().observe(this, observer);
    }

    @Override
    public boolean isTranslucent() {
        return true;
    }
}
